package http

import (
	"itodo/core/localwrap"
	"itodo/http/publicroute"
	"itodo/http/routes"
	"itodo/http/userroute"
	"time"

	"github.com/RocksonZeta/irisx"
	"github.com/RocksonZeta/wrap/errs"
	"github.com/RocksonZeta/wrap/utils/mathutil"
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/context"
	"github.com/kataras/iris/v12/core/router"
)

type SessionProvider struct {
}

const sessionTTL = 3600
const sessionKey = "sessionid"

func (s *SessionProvider) GetSessionId(ctx *irisx.Context) string {

	return ctx.GetCookie(sessionKey)
}
func (s *SessionProvider) SetSessionId(ctx *irisx.Context) {
	ctx.SetCookieLocal(sessionKey, mathutil.RandomStr(32, false), sessionTTL, true, "")
}
func (s *SessionProvider) Set(key string, value interface{}, secs int) error {
	red := localwrap.GetRedis()
	defer red.Close()
	red.SetJson(key, value, secs)
	return nil
}
func (s *SessionProvider) Get(key string, result interface{}) error {
	red := localwrap.GetRedis()
	defer red.Close()
	red.GetJson(key, result)
	return nil
}
func (s *SessionProvider) Refresh(key string, secs int) error {
	red := localwrap.GetRedis()
	defer red.Close()
	red.Expire(key, time.Duration(secs)*time.Second)
	return nil
}
func (s *SessionProvider) Remove(key string) error {
	red := localwrap.GetRedis()
	defer red.Close()
	red.Del(key)
	return nil
}
func (s *SessionProvider) UidKey() string {
	return "uid"
}

func NewApp() *iris.Application {
	// sessionsOptions := irisx.SessionOptions{
	// 	DatabaseUrl: localwrap.Config.Redis.Url,
	// 	Password:    localwrap.Config.Session.Password,
	// }
	// sessions := irisx.NewSessions(sessionsOptions)
	app := iris.New()
	app.ContextPool.Attach(func() context.Context {
		return &irisx.Context{
			Context:         context.NewContext(app),
			SessionProvider: &SessionProvider{},
		}
	})
	app.Use(ErrorFilter)
	app.Use(irisx.SidFilter)
	// app.HandleDir("/task", "static/dist", router.DirOptions{IndexName: "index.html"})

	// app.Use(sessions.Filter)
	tpl := iris.HTML("view", ".html")

	irisx.Enhance(tpl)
	// tpl.Delims("<%", "%>") // conflict with vue
	tpl.Reload(localwrap.Config.DevMode)
	app.RegisterView(tpl)

	// app.Get("/", func(ctx iris.Context) {
	// 	c := ctx.(*iriswrap.Context)
	// 	c.Ok(c.Session.Uid())
	// })
	route(app)
	app.HandleDir("/static", "static", router.DirOptions{IndexName: "_.html"})
	// app.HandleDir("/teamwork", "../itodo-front/dist")
	return app
}

func route(app *iris.Application) {
	userroute.RouteApiUser(app.Party("/api/user"))
	app.Layout("layout/public.html")
	publicroute.RouteIndex(app)

	app.Get("/team", func(ctx iris.Context) {
		c := ctx.(*irisx.Context)
		c.ServeFile("static/dist/index.html", false)
	})
	app.Get("/team/{f:path}", func(ctx iris.Context) {
		c := ctx.(*irisx.Context)
		f := ctx.Params().Get("f")
		fp := "static/dist/" + f
		err := c.ServeFile(fp, false)
		// _, err := os.Stat(fp)
		// fmt.Println("get "+f, err, os.IsExist(err))
		// if nil == err {
		// 	return
		// }
		if nil != err {
			c.ServeFile("static/dist/index.html", false)
		}
	})
}

func ErrorFilter(ctx iris.Context) {
	c := ctx.(*irisx.Context)
	defer func() {
		if e := recover(); e != nil {
			if err, ok := e.(*errs.Err); ok {
				routes.ReturnError(c, err)
				return
			}
			if err, ok := e.(error); ok {
				c.Err(1, err)
				return
			}
		}
	}()
	ctx.Next()
}
